---
title: Search for provider locations
summary: Multi-criteria dynamic search across provider locations, addresses, tax IDs, services, and MCO plans.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-08-21
library: SAIF.Business.View.Provider
reference_type: embedded
operation_id: OP-09
trigger: Caller populates SearchCriteria then invokes searchForProvider
---

# Search for provider locations

Executes a multi-criteria, dynamically assembled search across provider locations, addresses, tax IDs, other IDs, service types, and MCO plans, returning at most 300 ranked results.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-09 |
| **Trigger** | Caller populates `SearchCriteria` then invokes `searchForProvider()`; `resetSearchCriteria()` clears it |
| **Inputs** | `clsSearchCriteria` (`ProviderName`, `TaxId`, `OtherId`, `ProviderType`, `ServiceType`, `MCOName`, `BusinessPerson`, `Street`, `City`, `State`, `ZipCode`, `AreaCode`, `PhoneNum`) |
| **Outputs** | `Providers` (`clsProviders`, a read-only collection of `clsSearchResults`) |
| **Primary components** | `clsProviderSearch.searchForProvider` |
| **Entry point** | `SAIF.Business.View.Provider/clsProviderSearch.vb:89` |

## Steps

1. Reset the result collection; create a `SqlHelper.ResultSetQuery` bound to the DPI.
2. Evaluate `BusinessPerson`: `"BUSINESS"` → `BUSINESS_FLAG = 'Y'`, `"PERSON"` → `'N'`, anything else → `WHERE 1 = 1` ([BR-SRCH-004](../business-rules.md#br-srch-004-businessperson-selector-maps-to-business-flag)).
3. Append optional inner joins, each with a bind variable: tax ID → `provider_tax_id`; other ID → `provider_identity`; service type → `provider_service`; MCO plan → `mco_provider`.
4. Append optional predicates for name (prefix `LIKE` on `LAST_NAME_UPPER_CASE` or `BUSINESS_NAME_UPPER_CASE`), provider type, street (prefix `LIKE`), city, state, zip, area code, and phone (prefix `LIKE`) — all normalized per [BR-SRCH-008](../business-rules.md#br-srch-008-search-text-normalization) (upper-cased, trimmed, `-`/`.` stripped from phone).
   - If `ZipCode` is supplied: it must be numeric ([BR-SRCH-002](../business-rules.md#br-srch-002-zip-code-must-be-numeric)).
   - If `TaxId` is supplied: with hyphens removed, it must be fewer than 10 characters ([BR-SRCH-003](../business-rules.md#br-srch-003-tax-id-length-limit)).
5. If a provider name was supplied: `UNION` in the registered-name variant (`PRVSearchRegName`, joining `provider_tax_id`) so registered names are also matched ([BR-SRCH-005](../business-rules.md#br-srch-005-provider-name-search-also-matches-registered-names)).
6. Append `ORDER BY fullNAME ASC` and execute ([SQL-SRCH-01](../sql/SQL-SRCH-01-provider-search.md)).
7. Materialise each row into `clsSearchResults`, computing `SortName` via `FormatSortName` ([BR-SRCH-006](../business-rules.md#br-srch-006-sort-name-derivation)).
   - Stop condition: stop adding results once the collection exceeds 299 rows ([BR-SRCH-007](../business-rules.md#br-srch-007-search-results-capped-at-300-rows)) — the loop exits with no user-facing warning (an inline comment records that a warning "didn't work").
8. Validation rules [BR-SRCH-001](../business-rules.md#br-srch-001-at-least-one-search-field-is-required) … [BR-SRCH-003](../business-rules.md#br-srch-003-tax-id-length-limit) live on `clsSearchCriteria` and are evaluated by the BOF rule engine; `searchForProvider` itself does **not** check `IsValid` before querying.*

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([SearchCriteria populated]) --> S1[Reset Providers collection]
	S1 --> S2{BusinessPerson value?}
	S2 -->|BUSINESS| S3[BUSINESS_FLAG = 'Y']
	S2 -->|PERSON| S4[BUSINESS_FLAG = 'N']
	S2 -->|Other| S5[No flag filter]
	S3 --> S6["Append optional joins and<br>predicates"]
	S4 --> S6
	S5 --> S6
	S6 --> S7{Provider name supplied?}
	S7 -->|Yes| S8["UNION registered-name<br>variant"]
	S7 -->|No| S9[Execute single query]
	S8 --> S10["ORDER BY fullNAME ASC,<br>execute"]
	S9 --> S10
	S10 --> S11["Materialize rows into<br>clsSearchResults"]
	S11 --> S12{Rows > 299?}
	S12 -->|Yes| S13(["Stop loading, discard<br>remainder"])
	S12 -->|No| EndOk([Providers returned])
	S13 --> EndOk
```

## Failure and edge-case behavior

- No rows match: an empty `Providers` collection is returned.
- Result set exceeding 300 rows is silently truncated with no caller-visible warning ([BR-SRCH-007](../business-rules.md#br-srch-007-search-results-capped-at-300-rows)).
- `searchForProvider` does not check `clsSearchCriteria.IsValid` before executing, so validation rule breaches ([BR-SRCH-001](../business-rules.md#br-srch-001-at-least-one-search-field-is-required)–[BR-SRCH-003](../business-rules.md#br-srch-003-tax-id-length-limit)) do not by themselves prevent a query from running.*

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [SQL catalog](../sql/index.md)
- [Database tables](../database-tables.md)

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with ** could not be confirmed; treat as unknown until verified.

## Sources
- `SAIF.Business.View.Provider/clsProviderSearch.vb`
